/*
 * This file is a part of the SWFer project.
 *
 * Copyright (C) 2012 Michael Bradshaw <mjbshaw@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#include "Encode.hpp"
#include "ByteWriter.hpp"
#include "VectorStream.hpp"
#include "SoundFormat.hpp"

namespace swfer
{

template <>
const Packet encode<END>(const Tag<END>& tag)
{
    Packet p;
	p.header.code = END;
	p.header.length = 0;
    return p;
}
#if 0
template <>
const Packet encode<SHOW_FRAME>(const Tag<SHOW_FRAME>& tag)
{
    Packet p;
	p.header.code = SHOW_FRAME;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_SHAPE>(const Tag<DEFINE_SHAPE>& tag)
{
    Packet p;
	p.header.code = DEFINE_SHAPE;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<PLACE_OBJECT>(const Tag<PLACE_OBJECT>& tag)
{
    Packet p;
	p.header.code = PLACE_OBJECT;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<REMOVE_OBJECT>(const Tag<REMOVE_OBJECT>& tag)
{
    Packet p;
	p.header.code = REMOVE_OBJECT;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BITS>(const Tag<DEFINE_BITS>& tag)
{
    Packet p;
	p.header.code = DEFINE_BITS;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BUTTON>(const Tag<DEFINE_BUTTON>& tag)
{
    Packet p;
	p.header.code = DEFINE_BUTTON;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<JPEG_TABLES>(const Tag<JPEG_TABLES>& tag)
{
    Packet p;
	p.header.code = JPEG_TABLES;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<SET_BACKGROUND_COLOR>(const Tag<SET_BACKGROUND_COLOR>& tag)
{
    Packet p;
	p.header.code = SET_BACKGROUND_COLOR;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_FONT>(const Tag<DEFINE_FONT>& tag)
{
    Packet p;
	p.header.code = DEFINE_FONT;

	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_TEXT>(const Tag<DEFINE_TEXT>& tag)
{
    Packet p;
	p.header.code = DEFINE_TEXT;

    return p;
}

template <>
const Packet encode<DO_ACTION>(const Tag<DO_ACTION>& tag)
{
    Packet p;
	p.header.code = DO_ACTION;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_FONT_INFO>(const Tag<DEFINE_FONT_INFO>& tag)
{
    Packet p;
	p.header.code = DEFINE_FONT_INFO;
	
	p.header.length = p.data.size();
    return p;
}
#endif
template <>
const Packet encode<DEFINE_SOUND>(const Tag<DEFINE_SOUND>& tag)
{
    Packet p;
	p.header.code = DEFINE_SOUND;

	ovectorstream vs;

	ByteWriter w(vs);

	w.write(tag.id);
	w.write(tag.format);
	w.write(tag.rate);
	w.write(tag.size);
	w.write(tag.type);
	w.write(tag.sampleCount);

	if (tag.format == MP3)
	{
		w.write(tag.record.mp3.seekSamples);
	}
	else if (tag.format == ADPCM)
	{
		w.write(tag.record.adpcm.codeSize);
	}

	w.write(tag.data);

	vs.swap_vector(p.data);
	
	p.header.length = p.data.size();
    return p;
}
#if 0
template <>
const Packet encode<START_SOUND>(const Tag<START_SOUND>& tag)
{
    Packet p;
	p.header.code = START_SOUND;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BUTTON_SOUND>(const Tag<DEFINE_BUTTON_SOUND>& tag)
{
    Packet p;
	p.header.code = DEFINE_BUTTON_SOUND;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<SOUND_STREAM_HEAD>(const Tag<SOUND_STREAM_HEAD>& tag)
{
    Packet p;
	p.header.code = SOUND_STREAM_HEAD;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<SOUND_STREAM_BLOCK>(const Tag<SOUND_STREAM_BLOCK>& tag)
{
    Packet p;
	p.header.code = SOUND_STREAM_BLOCK;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BITS_LOSSLESS>(const Tag<DEFINE_BITS_LOSSLESS>& tag)
{
    Packet p;
	p.header.code = DEFINE_BITS_LOSSLESS;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BITS_JPEG2>(const Tag<DEFINE_BITS_JPEG2>& tag)
{
    Packet p;
	p.header.code = DEFINE_BITS_JPEG2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_SHAPE2>(const Tag<DEFINE_SHAPE2>& tag)
{
    Packet p;
	p.header.code = DEFINE_SHAPE2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BUTTON_CXFORM>(const Tag<DEFINE_BUTTON_CXFORM>& tag)
{
    Packet p;
	p.header.code = DEFINE_BUTTON_CXFORM;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<PROTECT>(const Tag<PROTECT>& tag)
{
    Packet p;
	p.header.code = PROTECT;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<PLACE_OBJECT2>(const Tag<PLACE_OBJECT2>& tag)
{
    Packet p;
	p.header.code = PLACE_OBJECT2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<REMOVE_OBJECT2>(const Tag<REMOVE_OBJECT2>& tag)
{
    Packet p;
	p.header.code = REMOVE_OBJECT2;

    return p;
}

template <>
const Packet encode<DEFINE_SHAPE3>(const Tag<DEFINE_SHAPE3>& tag)
{
    Packet p;
	p.header.code = DEFINE_SHAPE3;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_TEXT2>(const Tag<DEFINE_TEXT2>& tag)
{
    Packet p;
	p.header.code = DEFINE_TEXT2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BUTTON2>(const Tag<DEFINE_BUTTON2>& tag)
{
    Packet p;
	p.header.code = DEFINE_BUTTON2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BITS_JPEG3>(const Tag<DEFINE_BITS_JPEG3>& tag)
{
    Packet p;
	p.header.code = DEFINE_BITS_JPEG3;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BITS_LOSSLESS2>(const Tag<DEFINE_BITS_LOSSLESS2>& tag)
{
    Packet p;
	p.header.code = DEFINE_BITS_LOSSLESS2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_EDIT_TEXT>(const Tag<DEFINE_EDIT_TEXT>& tag)
{
    Packet p;
	p.header.code = DEFINE_EDIT_TEXT;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_SPRITE>(const Tag<DEFINE_SPRITE>& tag)
{
    Packet p;
	p.header.code = DEFINE_SPRITE;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<FRAME_LABEL>(const Tag<FRAME_LABEL>& tag)
{
    Packet p;
	p.header.code = FRAME_LABEL;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<SOUND_STREAM_HEAD2>(const Tag<SOUND_STREAM_HEAD2>& tag)
{
    Packet p;
	p.header.code = SOUND_STREAM_HEAD2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_MORPH_SHAPE>(const Tag<DEFINE_MORPH_SHAPE>& tag)
{
    Packet p;
	p.header.code = DEFINE_MORPH_SHAPE;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_FONT2>(const Tag<DEFINE_FONT2>& tag)
{
    Packet p;
	p.header.code = DEFINE_FONT2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<EXPORT_ASSETS>(const Tag<EXPORT_ASSETS>& tag)
{
    Packet p;
	p.header.code = EXPORT_ASSETS;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<IMPORT_ASSETS>(const Tag<IMPORT_ASSETS>& tag)
{
    Packet p;
	p.header.code = IMPORT_ASSETS;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<ENABLE_DEBUGGER>(const Tag<ENABLE_DEBUGGER>& tag)
{
    Packet p;
	p.header.code = ENABLE_DEBUGGER;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DO_INIT_ACTION>(const Tag<DO_INIT_ACTION>& tag)
{
    Packet p;
	p.header.code = DO_INIT_ACTION;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_VIDEO_STREAM>(const Tag<DEFINE_VIDEO_STREAM>& tag)
{
    Packet p;
	p.header.code = DEFINE_VIDEO_STREAM;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<VIDEO_FRAME>(const Tag<VIDEO_FRAME>& tag)
{
    Packet p;
	p.header.code = VIDEO_FRAME;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_FONT_INFO2>(const Tag<DEFINE_FONT_INFO2>& tag)
{
    Packet p;
	p.header.code = DEFINE_FONT_INFO2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<ENABLE_DEBUGGER2>(const Tag<ENABLE_DEBUGGER2>& tag)
{
    Packet p;
	p.header.code = ENABLE_DEBUGGER2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<SCRIPT_LIMITS>(const Tag<SCRIPT_LIMITS>& tag)
{
    Packet p;
	p.header.code = SCRIPT_LIMITS;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<SET_TAB_INDEX>(const Tag<SET_TAB_INDEX>& tag)
{
    Packet p;
	p.header.code = SET_TAB_INDEX;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<FILE_ATTRIBUTES>(const Tag<FILE_ATTRIBUTES>& tag)
{
    Packet p;
	p.header.code = FILE_ATTRIBUTES;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<PLACE_OBJECT3>(const Tag<PLACE_OBJECT3>& tag)
{
    Packet p;
	p.header.code = PLACE_OBJECT3;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<IMPORT_ASSETS2>(const Tag<IMPORT_ASSETS2>& tag)
{
    Packet p;
	p.header.code = IMPORT_ASSETS2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_FONT_ALIGN_ZONES>(const Tag<DEFINE_FONT_ALIGN_ZONES>& tag)
{
    Packet p;
	p.header.code = DEFINE_FONT_ALIGN_ZONES;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<CSM_TEXT_SETTINGS>(const Tag<CSM_TEXT_SETTINGS>& tag)
{
    Packet p;
	p.header.code = CSM_TEXT_SETTINGS;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_FONT3>(const Tag<DEFINE_FONT3>& tag)
{
    Packet p;
	p.header.code = DEFINE_FONT3;
	
	p.header.length = p.data.size();
    return p;
}
#endif
template <>
const Packet encode<SYMBOL_CLASS>(const Tag<SYMBOL_CLASS>& tag)
{
    Packet p;
	p.header.code = SYMBOL_CLASS;

	ovectorstream vs;

	ByteWriter w(vs);

	w.write(static_cast<uint16_t>(tag.symbols.size()));

	for (std::size_t i = 0; i < tag.symbols.size(); ++i)
	{
		w.write(tag.symbols[i].tag);
		w.write(tag.symbols[i].name);
	}

	vs.swap_vector(p.data);
	
	p.header.length = p.data.size();
    return p;
}
#if 0
template <>
const Packet encode<METADATA>(const Tag<METADATA>& tag)
{
    Packet p;
	p.header.code = METADATA;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_SCALING_GRID>(const Tag<DEFINE_SCALING_GRID>& tag)
{
    Packet p;
	p.header.code = DEFINE_SCALING_GRID;
	
	p.header.length = p.data.size();
    return p;
}
#endif
template <>
const Packet encode<DO_ABC>(const Tag<DO_ABC>& tag)
{
    Packet p;
	p.header.code = DO_ABC;

	ovectorstream vs;

	ByteWriter w(vs);
	w.write(tag.flags);
	w.write(tag.name);
	w.write(tag.data);

	vs.swap_vector(p.data);
	
	p.header.length = p.data.size();
    return p;
}
#if 0
template <>
const Packet encode<DEFINE_SHAPE4>(const Tag<DEFINE_SHAPE4>& tag)
{
    Packet p;
	p.header.code = DEFINE_SHAPE4;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_MORPH_SHAPE2>(const Tag<DEFINE_MORPH_SHAPE2>& tag)
{
    Packet p;
	p.header.code = DEFINE_MORPH_SHAPE2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_SCENE_AND_FRAME_LABEL_DATA>(const Tag<DEFINE_SCENE_AND_FRAME_LABEL_DATA>& tag)
{
    Packet p;
	p.header.code = DEFINE_SCENE_AND_FRAME_LABEL_DATA;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BINARY_DATA>(const Tag<DEFINE_BINARY_DATA>& tag)
{
    Packet p;
	p.header.code = DEFINE_BINARY_DATA;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_FONT_NAME>(const Tag<DEFINE_FONT_NAME>& tag)
{
    Packet p;
	p.header.code = DEFINE_FONT_NAME;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<START_SOUND2>(const Tag<START_SOUND2>& tag)
{
    Packet p;
	p.header.code = START_SOUND2;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_BITS_JPEG4>(const Tag<DEFINE_BITS_JPEG4>& tag)
{
    Packet p;
	p.header.code = DEFINE_BITS_JPEG4;
	
	p.header.length = p.data.size();
    return p;
}

template <>
const Packet encode<DEFINE_FONT4>(const Tag<DEFINE_FONT4>& tag)
{
    Packet p;
	p.header.code = DEFINE_FONT4;
	
	p.header.length = p.data.size();
    return p;
}
#endif
}